package han.Chensing.CCirnosLibrary.map;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import han.Chensing.CCirnosLibrary.func.Match;
import han.Chensing.CCirnosLibrary.func.Query;

public class ItemNode implements Serializable {
    private static final long serialVersionUID= 1145141919810L;
    private ArrayList<ItemNode> childNodes;
    private String originalName;
    private String name;
    private String link;
    private String fakeLink;
    private String rootLink;
    private ItemFlag itemFlag;
    private ItemNode parent;
    private boolean folder;
    private boolean rootNode=false;
    private String fileMD5;
    private transient ItemDecInfo itemDecInfo;

    public ItemNode(){
        this.childNodes=new ArrayList<>();
        this.itemFlag=new ItemFlag();
    }

    public ArrayList<ItemNode> getChildNodes() {
        return childNodes;
    }

    public void setChildNodes(ArrayList<ItemNode> childNodes) {
        this.childNodes = childNodes;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getLink() {
        return link;
    }

    public void setLink(String link) {
        this.link = link;
    }

    public ItemFlag getItemFlag() {
        return itemFlag;
    }

    public void setItemFlag(ItemFlag itemFlag) {
        this.itemFlag = itemFlag;
    }

    public boolean isList(){
        return childNodes.size()!=0||folder;
    }

    public ItemNode getParent() {
        return parent;
    }

    public void setParent(ItemNode parent) {
        this.parent = parent;
    }

    public String getOriginalName() {
        return originalName;
    }

    public void setOriginalName(String originalName) {
        this.originalName = originalName;
    }

    public void setFakeLink(String fakeLink) {
        this.fakeLink = fakeLink;
    }

    public String getFakeLink() {
        return fakeLink;
    }

    public boolean isFolder() {
        return folder;
    }

    public void setFolder(boolean folder) {
        this.folder = folder;
    }

    public ItemDecInfo getItemDecInfo() {
        return itemDecInfo;
    }

    public void setItemDecInfo(ItemDecInfo itemDecInfo) {
        this.itemDecInfo = itemDecInfo;
    }

    public boolean isRootNode() {
        return rootNode;
    }

    public void setRootNode(boolean rootNode) {
        this.rootNode = rootNode;
    }

    public String getFileMD5() {
        return fileMD5;
    }

    public void setFileMD5(String fileMD5) {
        this.fileMD5 = fileMD5;
    }

    public String getRootLink() {
        return rootLink;
    }

    public void setRootLink(String rootLink) {
        this.rootLink = rootLink;
    }

    public void find(Match<ItemNode> match, List<ItemNode> itemNodes, boolean findChild){
        if (itemNodes==null)
            return;
        if (match.match(this))
            itemNodes.add(this);
        for (ItemNode node:childNodes) {
            node.find(match, itemNodes,findChild);
        }
    }

    public void find(Match<ItemNode> match, List<ItemNode> itemNodes){
        find(match, itemNodes,true);
    }

    public void query(Query query){
        ItemNode parent = getParent();
        if (!isList()){
            query.query(Query.QueryType.Node,this, parent);
            return;
        }
        query.query(Query.QueryType.MenuIn,this, parent);
        for (ItemNode childNode : childNodes)
            childNode.query(query);
        query.query(Query.QueryType.MenuOut,this, parent);
    }

    public void setAllItemDecInfo(ItemDecInfo itemDecInfo){
        query((queryType, node, parent) -> {
            if (queryType== Query.QueryType.MenuIn||queryType== Query.QueryType.Node)
                node.setItemDecInfo(itemDecInfo);
        });
    }

    public void clear(){
        if (!isList())
            return;
        Iterator<ItemNode> iterator = childNodes.iterator();
        while (iterator.hasNext()){
            ItemNode next = iterator.next();
            next.clear();
            iterator.remove();
        }
    }

    public void printMap(boolean listChild){
        if (isList()) {
            for (ItemNode itemNode : childNodes)
                printMap(itemNode, 0, listChild);
            return;
        }
        printMap(this,0,listChild);
    }

    public void printMap(){
        printMap(true);
    }

    public static void printMap(ItemNode itemNode, int depth,boolean listChild){
        ArrayList<ItemNode> childNodes = itemNode.getChildNodes();
        for(int i=0;i<depth;i++)
            System.out.print("  ");
        boolean list = itemNode.isList();
        if (list &&listChild){
            System.out.println("& "+itemNode.getName());
            for (ItemNode childNode : childNodes)
                printMap(childNode,depth+1, true);
            return;
        }
        if (!listChild&& list)
            System.out.print("& ");
        if (!list) {
            System.out.printf("  %s - %s [ ", itemNode.getName(), itemNode.getLink());
            for (String flag : itemNode.getItemFlag().getFlags())
                System.out.print(flag + " ");
            System.out.println("]");
            return;
        }
        System.out.println(itemNode.getName());
    }

    @Override
    public String toString() {
        return "ItemNode{" +
                "originalName='" + originalName + '\'' +
                ", name='" + name + '\'' +
                ", link='" + link + '\'' +
                ", fakeLink='" + fakeLink + '\'' +
                ", rootLink='" + rootLink + '\'' +
                ", itemFlag=" + itemFlag +
                ", folder=" + folder +
                ", rootNode=" + rootNode +
                ", fileMD5='" + fileMD5 + '\'' +
                '}';
    }
}
